package net.gdface.utils;

import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.base.MoreObjects.firstNonNull;

import com.google.common.base.Strings;

public class MatchPatternInfo {
	/** 匹配任意字符的对象 */
	public static final MatchPatternInfo ANY = of("*");
	/** 用于匹配的字符 */
	private String pattern;
	private MatchType matchType;
	
	public MatchPatternInfo() {
		super();
	}
	
	public MatchPatternInfo(String pattern, MatchType matchType) {
		super();
		this.pattern = pattern;
		this.matchType = matchType;
	}

	public String getPattern() {
		return pattern;
	}
	public void setPattern(String pattern) {
		this.pattern = pattern;
	}
	public MatchType getMatchType() {
		return matchType;
	}
	public void setMatchType(MatchType matchType) {
		this.matchType = matchType;
	}
	/**
	 * @return {@code true} if pattern or matchType is null
	 */
	public boolean nullPattern(){
		return null == pattern || null == matchType ;
	}
	public boolean match(MatchPatternInfo inputPatternInfo){
		if(!nullPattern() && !nullPattern(inputPatternInfo)){
			return matchType.match(inputPatternInfo.pattern, pattern);
		}
		return false;
	}
	public boolean match(String input){
		if(!nullPattern() && !Strings.isNullOrEmpty(input)){
			return matchType.match(input, pattern);
		}
		return false;
	}
	public boolean isDefaultMatch(){
		return MatchType.DEFAULT.equals(matchType);
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((matchType == null) ? 0 : matchType.hashCode());
		result = prime * result + ((pattern == null) ? 0 : pattern.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		MatchPatternInfo other = (MatchPatternInfo) obj;
		if (matchType != other.matchType)
			return false;
		if (pattern == null) {
			if (other.pattern != null)
				return false;
		} else if (!pattern.equals(other.pattern))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "MatchPatternInfo [" + (pattern != null ? "pattern=" + pattern + ", " : "")
				+ (matchType != null ? "matchType=" + matchType : "") + "]";
	}

	/**
	 * 根据模式字符串({@code pattern})的格式归一化,<br>
	 * 字母,数字,'_','/'视为普通字符
	 * @param pattern
	 * @return 返回归一化的模式字符串和对应的匹配类型
	 */
	public static MatchPatternInfo of(String pattern){
		if(isNullOrEmpty(pattern)){
			return null;
		}
		/** 根据pattern格式决定匹配类型 */
		if(pattern.matches("[\\w/]+")) {
			return new MatchPatternInfo(pattern,MatchType.DEFAULT);
		}else if(pattern.matches("[\\w/]+\\*")) {
			return new MatchPatternInfo(pattern.replace("*", ""),MatchType.LEFT);
		}else if(pattern.matches("\\*[\\w/]+")) {
			return new MatchPatternInfo(pattern.replace("*", ""),MatchType.RIGHT);
		}else if(pattern.matches("\\*[\\w/]+\\*")) {
			return new MatchPatternInfo(pattern.replace("*", ""),MatchType.INCLUDE);
		}else if(pattern.matches("\\*")) {
			return new MatchPatternInfo(".*",MatchType.REGEX);
		}else {
			return new MatchPatternInfo(pattern, MatchType.REGEX);
		}
	}
	/**
	 * 根据输入的模式字符串创建{@code MatchPatternInfo}实例
	 * @param pattern
	 * @param lenient 是否为宽容模式,<br>
	 * 					为{@code false}时,字母,数字,'_','/'视为普通字符,参见{@link #of(String)}<br>
	 * 					为{@code true}时,字母,数字,'_','/'和'-',':','@','#','%'都视为普通字符。
	 * @since 2.7.9
	 */
	public static MatchPatternInfo of(String pattern,boolean lenient){
		if(!lenient) {
			return of(pattern);
		}
		return of(pattern,":\\-/@#%");
	}
	/**
	 * 根据输入的模式字符串创建{@code MatchPatternInfo}实例
	 * @param pattern
	 * @param lenientChars  宽容字符列表,字母,数字,'_'和列表中的字符都视为普通字符,
	 * 										为{@code null}或空时只有字母,数字,'_'被视为普通字符
	 * @since 2.7.9
	 */
	public static MatchPatternInfo of(String pattern,char... lenientChars){
		if(null == lenientChars) {
			lenientChars = new char[0];
		}
		return of(pattern,new String(lenientChars));
	}
	/**
	 * 根据输入的模式字符串创建{@code MatchPatternInfo}实例
	 * @param pattern
	 * @param lenientChars  宽容字符列表,字母,数字,'_'和列表中的字符都视为普通字符,
	 * 										为{@code null}或空时只有字母,数字,'_'被视为普通字符
	 * @since 2.7.9
	 */
	public static MatchPatternInfo of(String pattern,String lenientChars){
		if(isNullOrEmpty(pattern)){
			return null;
		}
		String plainCharsRegex = "[\\w" + firstNonNull(lenientChars,"") + "]+";
		/** 根据pattern格式决定匹配类型 */
		if(pattern.matches(plainCharsRegex)) {
			return new MatchPatternInfo(pattern,MatchType.DEFAULT);
		}else if(pattern.matches(plainCharsRegex+"\\*")) {
			return new MatchPatternInfo(pattern.replace("*", ""),MatchType.LEFT);
		}else if(pattern.matches("\\*"+plainCharsRegex)) {
			return new MatchPatternInfo(pattern.replace("*", ""),MatchType.RIGHT);
		}else if(pattern.matches("\\*"+plainCharsRegex+"\\*")) {
			return new MatchPatternInfo(pattern.replace("*", ""),MatchType.INCLUDE);
		}else if(pattern.matches("\\*")) {
			return new MatchPatternInfo(".*",MatchType.REGEX);
		}else {
			return new MatchPatternInfo(pattern, MatchType.REGEX);
		}
	}
	/**
	 * @return {@code true} if patternInfo or patternInfo.pattern or patternInfo.matchType is null
	 */
	public static boolean nullPattern(MatchPatternInfo patternInfo){
		return null == patternInfo || patternInfo.nullPattern() ;
	}
}
